package com.keyue.isolate.context;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.List;
import java.util.Stack;

/**
 * @author gree
 * @Date 2025/04/28
 * @Created by fanzhenyu
 */
public class DataIsolateContextHolder {

    private static Logger logger = LoggerFactory.getLogger(DataIsolateContextHolder.class);

    /**
     * 数据隔离策略
     * 使用栈存储 多个数据隔离注解 存多层
     */
    private static final ThreadLocal<Stack<List<DataIsolateValue>>> CONTEXT_HOLDER = new ThreadLocal<>();

    /**
     * 忽略注解前的数据隔离
     */
    private static final ThreadLocal<Boolean> IGNORE_BEFORE_FLAG_HOLDER = new ThreadLocal<>();

    /**
     * 忽略注解后的数据隔离
     */
    private static final ThreadLocal<Boolean> IGNORE_AFTER_FLAG_HOLDER = new ThreadLocal<>();

    /**
     * 设置上下文
     *
     * @param dataIsolateValues
     */
    public static void setContextValue(List<DataIsolateValue> dataIsolateValues) {
        if (null == CONTEXT_HOLDER.get()) {
            CONTEXT_HOLDER.set(new Stack<>());
        }
        Stack<List<DataIsolateValue>> stack = CONTEXT_HOLDER.get();
        stack.push(dataIsolateValues);
    }

    public static void clear() {
        Stack<List<DataIsolateValue>> stack = CONTEXT_HOLDER.get();
        if (null == stack) {
            CONTEXT_HOLDER.remove();
            return;
        }

        stack.pop();
        if (stack.isEmpty()) {
            CONTEXT_HOLDER.remove();
        }
    }

    public static List<DataIsolateValue> get() {
        Stack<List<DataIsolateValue>> stack = CONTEXT_HOLDER.get();
        if (null == stack) {
            return Collections.emptyList();
        }

        return stack.peek();
    }

    public static boolean hasContext() {
        return null != CONTEXT_HOLDER.get();
    }


    /**
     * 忽略前置数据隔离
     * 数据隔离切面A->ignore切面B->数据隔离切面C 此时B开启了忽略前置 直接忽略切面A
     * @return
     */
    public static boolean needIgnoreBefore() {
        Boolean ignore = IGNORE_BEFORE_FLAG_HOLDER.get();
        return null != ignore && ignore;
    }

    /**
     * ignore after有值 说明进入该切面之前的切面开启了ignoreAfter 忽略后置数据隔离
     * 如：数据隔离切面A->ignore切面B->数据隔离切面C 此时B开启了忽略后置 直接忽略切面C
     * @return
     */
    public static boolean needIgnoreAfter() {
        Boolean ignore = IGNORE_AFTER_FLAG_HOLDER.get();
        return null != ignore && ignore;
    }

    public static void unMarkIgnore() {
        IGNORE_BEFORE_FLAG_HOLDER.remove();
        IGNORE_AFTER_FLAG_HOLDER.remove();
    }

    public static void markIgnoreBefore() {
        IGNORE_BEFORE_FLAG_HOLDER.set(true);
    }

    public static void markIgnoreAfter() {
        IGNORE_AFTER_FLAG_HOLDER.set(true);
    }
}
